
package com.hexiang.web;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import com.hexiang.domain.Book;

@RestController
public class WebReqRestTemplateController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getCall")
    public String getCall() {
        String url = "http://www.suning.com";
        return restTemplate.getForObject(url, String.class);

    }

    @GetMapping("/getCallByEntity")
    public void remoteCallByEntity() {
        String url = "http://www.test.com";
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
        // 获取响应体
        String body = responseEntity.getBody();
        // 获取响应码
        HttpStatus statusCode = responseEntity.getStatusCode();
        // 获取响应码值
        int statusCodeValue = responseEntity.getStatusCodeValue();
        // 获取响应头
        HttpHeaders headers = responseEntity.getHeaders();

        System.out.println("body：" + body);
        System.out.println("statusCode：" + statusCode);
        System.out.println("statusCodeValue：" + statusCodeValue);
        System.out.println("headers：" + headers);

        // 判断请求是否发生异常
        if (!responseEntity.getStatusCode().is2xxSuccessful()) {
            // 抛出异常
            throw new RestClientException(responseEntity.getBody());
        }

        return;
    }

    @GetMapping("/postCall")
    public void postCall() {
        // 请求地址
        String url = "http://jsonplaceholder.typicode.com/posts";

        // 要发送的数据对象
        Book book = new Book();
        book.setName("Spring Boot开发指南");
        book.setAuthor("hangge");
        book.setPrice(50f);
        book.setPublicationDate(new Date());
        // 发送post请求，并输出结果
        String result = restTemplate.postForObject(url, book, String.class);
        System.out.println(result);
        return;
    }

    @GetMapping("/postCallform")
    public void postCallform() {
        // 请求地址
        String url = "http://jsonplaceholder.typicode.com/posts";

        // 请求头设置
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        // 提交参数设置
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("title", "abc");
        map.add("body", "航歌");

        // 组装请求体
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);

        // 发送post请求，并输出结果
        String result = restTemplate.postForObject(url, request, String.class);
        System.out.println(result);
        return;
    }

    @GetMapping("/postCallEntity")
    public void postCallEntity() {
        // 请求地址
        String url = "http://jsonplaceholder.typicode.com/posts";
        // 要发送的数据对象
        Book book = new Book();
        book.setName("Spring Boot开发指南");
        book.setAuthor("hangge");
        book.setPrice(50f);
        book.setPublicationDate(new Date());

        // 发送post请求，并输出结果
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, book, String.class);
        // 获取响应体
        String body = responseEntity.getBody();
        // 获取响应码
        HttpStatus statusCode = responseEntity.getStatusCode();
        // 获取响应码值
        int statusCodeValue = responseEntity.getStatusCodeValue();
        // 获取响应头
        HttpHeaders headers = responseEntity.getHeaders();

        System.out.println("body：" + body);
        System.out.println("statusCode：" + statusCode);
        System.out.println("statusCodeValue：" + statusCodeValue);
        System.out.println("headers：" + headers);
        return;
    }

    @GetMapping("/postCallEntityForm")
    public void postCallEntityForm() {
        // 请求地址
        String url = "http://jsonplaceholder.typicode.com/posts";

        // 请求头设置
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        // 提交参数设置
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("title", "abc");
        map.add("body", "航歌");

        // 组装请求体
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);

        // 发送post请求，并输出结果
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
        // 获取响应体
        String body = responseEntity.getBody();
        // 获取响应码
        HttpStatus statusCode = responseEntity.getStatusCode();
        // 获取响应码值
        int statusCodeValue = responseEntity.getStatusCodeValue();
        // 获取响应头
        HttpHeaders respoensHeaders = responseEntity.getHeaders();

        System.out.println("body：" + body);
        System.out.println("statusCode：" + statusCode);
        System.out.println("statusCodeValue：" + statusCodeValue);
        System.out.println("headers：" + respoensHeaders);
        return;
    }

    @GetMapping("/postForLocation")
    public void postForLocation() {
        // 请求地址
        String url = "http://jsonplaceholder.typicode.com/posts";

        // 要发送的数据对象
        MultiValueMap<String, String> request = new LinkedMultiValueMap<>();
        request.add("username", "hangge");
        request.add("password", "123456");

        // 发送post请求，并输出结果
        URI uri = restTemplate.postForLocation(url, request);
        System.out.println(uri);
        return;
    }

    @GetMapping("/exchangeForGet")
    public void exchangeForGet() {
        String url = "http://jsonplaceholder.typicode.com/posts/5";
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        // 获取响应体
        String body = responseEntity.getBody();
        // 获取响应码
        HttpStatus statusCode = responseEntity.getStatusCode();
        // 获取响应码值
        int statusCodeValue = responseEntity.getStatusCodeValue();
        // 获取响应头
        HttpHeaders headers = responseEntity.getHeaders();

        System.out.println("body：" + body);
        System.out.println("statusCode：" + statusCode);
        System.out.println("statusCodeValue：" + statusCodeValue);
        System.out.println("headers：" + headers);
        return;
    }

    @GetMapping("/exchangeForPost")
    public void exchangeForPost() {
        // 请求地址
        String url = "http://jsonplaceholder.typicode.com/posts";

        // 请求头设置
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 提交参数设置
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("userId", "222");
        map.add("title", "abc");
        map.add("body", "航歌");

        // 组装请求体
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);

        // 发送post请求，并输出结果
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
        // 获取响应体
        String body = responseEntity.getBody();
        // 获取响应码
        HttpStatus statusCode = responseEntity.getStatusCode();
        // 获取响应码值
        int statusCodeValue = responseEntity.getStatusCodeValue();
        // 获取响应头
        HttpHeaders responseHeaders = responseEntity.getHeaders();

        System.out.println("body：" + body);
        System.out.println("statusCode：" + statusCode);
        System.out.println("statusCodeValue：" + statusCodeValue);
        System.out.println("headers：" + responseHeaders);
        return;
    }

    @GetMapping("/download")
    public void download() {
        // 记录下开始下载时的时间
        Instant now = Instant.now();
        // 待下载的文件地址
        String url = "http://www.hangge.com/blog/images/logo.png";
        ResponseEntity<byte[]> rsp = restTemplate.getForEntity(url, byte[].class);
        System.out.println("状态码：" + rsp.getStatusCode());
        try {
            // 将下载下来的文件内容保存到本地
            String targetPath = "/Users/hangge/Desktop/logo.png";
            Files.write(Paths.get(targetPath), Objects.requireNonNull(rsp.getBody(), "未获取到下载文件"));
        } catch (IOException e) {
            System.out.println("文件写入失败：" + e.getMessage());
        }
        System.out.println("文件下载完成，耗时：" + ChronoUnit.MILLIS.between(now, Instant.now()) + " 毫秒");
        return;
    }

    @GetMapping("/bigDownload")
    public void bigDownload() {
        // 记录下开始下载时的时间
        Instant now = Instant.now();
        // 待下载的文件地址
        String url = "http://www.hangge.com/blog/images/logo.png";
        // 文件保存的本地路径
        String targetPath = "/Users/hangge/Desktop/logo.png";
        // 定义请求头的接收类型
        RequestCallback requestCallback = request -> request.getHeaders()
                .setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
        // 对响应进行流式处理而不是将其全部加载到内存中
        restTemplate.execute(url, HttpMethod.GET, requestCallback, clientHttpResponse -> {
            Files.copy(clientHttpResponse.getBody(), Paths.get(targetPath));
            return null;
        });
        System.out.println("文件下载完成，耗时：" + ChronoUnit.MILLIS.between(now, Instant.now()) + " 毫秒");
        return;
    }

    @GetMapping("/uploadSender")
    public void uploadSender() {
        // 上传接口
        String url = "http://localhost:8080/upload";
        // 待上传的文件
        String filePath = "/Users/hangge/Desktop/test.txt";

        // 封装请求参数
        FileSystemResource resource = new FileSystemResource(new File(filePath));
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("myFile", resource);
        param.add("param1", "12345");
        param.add("param2", "hangge");

        // 发送请求并输出结果
        System.out.println("--- 上传文件 ---");
        String s = restTemplate.postForObject(url, param, String.class);
        System.out.println(s);
    }

    @PostMapping("/uploadReceiver")
    public String upload(String param1, String param2, MultipartFile myFile) {
        System.out.println("--- 接收文件 ---");
        System.out.println("param1：" + param1);
        System.out.println("param2：" + param2);
        String originalFilename = myFile.getOriginalFilename();
        System.out.println("文件原始名称：" + originalFilename);
        try {
            String string = new String(myFile.getBytes(), "UTF-8");
            System.out.println("文件内容：" + string);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 处理文件内容...
        return "OK";
    }
}